package com.wty.zookeeper;

import lombok.extern.slf4j.Slf4j;
import org.apache.zookeeper.*;
import org.apache.zookeeper.data.ACL;
import org.apache.zookeeper.data.Id;
import org.apache.zookeeper.data.Stat;
import org.apache.zookeeper.server.auth.DigestAuthenticationProvider;

import java.io.IOException;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.List;

@Slf4j
public class ZookeeperDemo implements Watcher {

    public static void main(String args[]) throws IOException, InterruptedException, KeeperException, NoSuchAlgorithmException {
        /*ZooKeeper zk=new ZooKeeper("127.0.0.1:2181",10000,watchedEvent -> {
            if(watchedEvent.getState()==Event.KeeperState.SyncConnected){
                if(watchedEvent.getType()==Event.EventType.None){
                    System.out.println("初始化连接");
                }else if(watchedEvent.getType()== Event.EventType.NodeCreated){
                    System.out.println("NodeCreated");
                }else if(watchedEvent.getType()== Event.EventType.NodeDeleted){
                    System.out.println("NodeDeleted");
                }else if(watchedEvent.getType()== Event.EventType.NodeDataChanged){
                    System.out.println("NodeDataChanged");
                }else if(watchedEvent.getType()== Event.EventType.NodeChildrenChanged){
                    System.out.println("NodeChildrenChanged");
                }
            }
        });*/

        ZooKeeper zk=new ZooKeeper("127.0.0.1:2181",10000,new ZookeeperDemo());
        Thread.sleep(2000);

        //createNodeSync(zk);
        //createNode(zk);
        //deleteNodeSync(zk,"/persistent");
        //ssetDataSync(zk,"/persistent","testdata"); //create的同时调用这个方法的话会报错
        //exists(zk,"/persistent",false);
        //System.out.println(getDataSync(zk,"/persistent",false));
        //getchildren(zk,"/persistent");
        setAclSync(zk);
        unConnect(zk);
    }

    /**
     * 实现接口的回掉，上面是lambda版回调
     * @param watchedEvent
     */
    @Override
    public void process(WatchedEvent watchedEvent) {
        if(watchedEvent.getState()==Event.KeeperState.SyncConnected){
            if(watchedEvent.getType()==Event.EventType.None&& null == watchedEvent.getPath()){
                System.out.println("初始化连接");
            }else if(watchedEvent.getType()== Event.EventType.NodeCreated){
                System.out.println("NodeCreated");
            }else if(watchedEvent.getType()== Event.EventType.NodeDeleted){
                System.out.println("NodeDeleted");
            }else if(watchedEvent.getType()== Event.EventType.NodeDataChanged){
                System.out.println("NodeDataChanged");
            }else if(watchedEvent.getType()== Event.EventType.NodeChildrenChanged){
                System.out.println("NodeChildrenChanged");
            }
        }
    }




    /**
     *  同步创建节点
     *  临时节点可以重复创建，持久化节点不能重复创建
     * @param zooKeeper
     * @throws KeeperException
     * @throws InterruptedException
     */
    public static void createNodeSync(ZooKeeper zooKeeper) throws KeeperException, InterruptedException {
        //String nodePath=zooKeeper.create("/ephemeral","wty".getBytes(),ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
        String nodePath=zooKeeper.create("/persistent","wty".getBytes(),ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
        //String nodePath=zooKeeper.create("/test","wty".getBytes(),ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);
        //String nodePath=zooKeeper.create("/test","wty".getBytes(),ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT_SEQUENTIAL);
        System.out.println(nodePath);
    }


    /**
     * 异步创建节点匿名内部类版
     * @param zooKeeper
     */
    public static void createNode(ZooKeeper zooKeeper){
        zooKeeper.create("/eohemeral", "nosync".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL, new AsyncCallback.StringCallback() {
            public void processResult(int resultCode, String path, Object ctx, String name) {
                System.out.println(resultCode);
                System.out.println(path);
                System.out.println(ctx);
                System.out.println(name);
            }
        },"create");
    }

    /**
     * 异步创建节点lambda版
     * @param zooKeeper
     */
    public static void createNodelambda(ZooKeeper zooKeeper){
        zooKeeper.create("/eohemeral", "nosync".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL, (result,path,ctx,name)->{
            System.out.println(result);
            System.out.println(path);
            System.out.println(ctx);
            System.out.println(name);
        },"create");
    }

    /**
     * 同步删除，有子节点时无法删除，版本号不一致无法删除,版本号指的是dataversion   version -1 代表最新的版本
     * @param zookeeper
     * @throws KeeperException
     * @throws InterruptedException
     */
    public static void deleteNodeSync(ZooKeeper zookeeper,String path) throws KeeperException, InterruptedException {
        zookeeper.delete(path,-1);
    }

    /**
     * 同步设置数据
     * @param zooKeeper
     * @param path
     * @param data
     * @throws KeeperException
     * @throws InterruptedException
     */
    public static void setDataSync(ZooKeeper zooKeeper,String path,String data) throws KeeperException, InterruptedException {
        zooKeeper.setData(path,data.getBytes(),-1);
    }

    /**
     * 同步获取数据1，是否用已有的watcher
     * @param zooKeeper
     * @param path
     * @param flag
     * @return
     * @throws KeeperException
     * @throws InterruptedException
     */
    public static byte[] getDataSync(ZooKeeper zooKeeper,String path,boolean flag) throws KeeperException, InterruptedException {
        Stat stat=new Stat();
        byte[] data=zooKeeper.getData(path,flag,stat);
        System.out.println(stat);
        return data;
    }

    public static byte[] getDataSync(ZooKeeper zooKeeper,String path,Watcher watcher) throws KeeperException, InterruptedException {
        Stat stat=new Stat();
        byte[] data= zooKeeper.getData(path,watcher,stat);
        System.out.println(stat);
        return data;
    }


    /**
     * 判断节点是否存在
     * @param zooKeeper
     * @param path
     * @param flag
     * @return
     * @throws KeeperException
     * @throws InterruptedException
     */
    public static Stat exists(ZooKeeper zooKeeper,String path,boolean flag) throws KeeperException, InterruptedException {
        Stat stat= zooKeeper.exists(path,flag);
        if(stat!=null){
            System.out.println("节点是存在的");
        }else{
            System.out.println("节点不存在");
        }
        return stat;
    }


    public static void getchildren(ZooKeeper zooKeeper,String path) throws KeeperException, InterruptedException {
        List<String> list= zooKeeper.getChildren(path,false);
        list.stream().forEach(System.out::println);

    }

    public static void setAclSync(ZooKeeper zooKeeper) throws NoSuchAlgorithmException, KeeperException, InterruptedException {
        List<ACL> aclList=new ArrayList<ACL>();
        String authStr=DigestAuthenticationProvider.generateDigest("wty:wty709568");
        ACL acl=new ACL(ZooDefs.Perms.ALL,new Id("auth",authStr));
        aclList.add(acl);
        zooKeeper.setACL("/persistent",aclList,-1);
    }


    /**
     * 断开连接，创建临时节点就去除了
     * @param zooKeeper
     * @throws InterruptedException
     */
    public static void unConnect(ZooKeeper zooKeeper) throws InterruptedException {
        zooKeeper.close();
        System.out.println("断开连接");
    }




}
